package org.mtmi.ui.controls;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.mtmi.io.IControlIO;
import org.mtmi.io.controls.ValueTransformerIO;
import org.mtmi.ui.GraphicUtil;
import org.mtmi.ui.controls.curve.CurveManager;
import org.mtmi.ui.controls.curve.CurveValueTransformer;
import org.mtmi.ui.controls.curve.ICurveManagerListener;
import org.mtmi.ui.controls.curve.IValueTransformer;
import org.mtmi.ui.controls.curve.IdentifiyValueTransformer;
import org.mtmi.ui.controls.edits.ValueTransformerControlEditor;
import org.mtmi.ui.drawables.IDrawable;
import org.mtmi.ui.edit.IControlEditor;
import org.mtmi.ui.layouts.LayoutData;
import org.mtmi.ui.scenes.COLOR;
import org.mtmi.ui.scenes.Scene;

/**
 * A Value transformer should be linked to a {@link IValueGenerator},
 * it role is to apply transformation on input value before sending it to connected control.
 * <p>
 * This control is displayed only when scene is editing.
 */
public class ValueTransformer extends AbstractRangeValueControl
 implements ICurveManagerListener
{
	private static final int MG = 10;
	
	private IValueTransformer value_tranformer; //the function
	
	public ValueTransformer(Scene scene, int _flags) {
		super(scene, _flags);
		//default:
		setBackground( COLOR.grey30 );
		setForeground( COLOR.grey80 );
		
		//by default:
		value_tranformer = new IdentifiyValueTransformer();
		
		setSize( computeSize( new LayoutData(scene) ) );
		
		CurveManager.addListener( this );
	}
	
	@Override
	public void dispose() {
		CurveManager.removeListener( this );
		super.dispose();
	}
	
	/** @return the function currently applied on input value */
	public IValueTransformer getValueTransformer() { return value_tranformer; }
	
	/** change current value transformer, null to reset to identify */
	public void setValueTransformer( IValueTransformer vt ) 
	{
		if( vt == null ) {
			value_tranformer = new IdentifiyValueTransformer();
		} else {
			value_tranformer = vt;
		}
		//update value to listeners ?
		if( getValueController()!=null ) {
			valueControllerValueChanged();
		}
	}
	
	@Override
	public Point computeSize( LayoutData l ) {
		
		IDrawable d = value_tranformer.getDrawable();
		
		if( d==null ) {
			return new Point( 30, 30 ); //default
		} else {
			Point p =d.computeSize( 24, 24 );
			p.x += 2*MG;
			p.y += 2*MG;
			return p;
		}
	}

	@Override
	public boolean containsTouch(TouchControlEvent e) {
		if( getScene().isEditing() ) {
			return GraphicUtil.rectContains( location, size, e.x, e.y );
		} else {
			return false;
		}
	}

	@Override
	public void paint(GC gc) 
	{
		if( !getScene().isEditing() ) return;
		
		gc.setForeground( getForeground() );
		gc.setBackground( getBackground() );
		gc.setLineWidth( borderWidth );
		gc.fillRectangle( location.x, location.y, size.x, size.y );
		gc.drawRectangle( location.x, location.y, size.x, size.y );
		
		IDrawable d = value_tranformer.getDrawable();
		if( d!=null ) {
			d.paint( gc, location.x+MG, location.y+MG, size.x-2*MG, size.y-2*MG, IDrawable.NORMAL );
		}
	}

	@Override
	protected void valueControllerValueChanged() {
		float vi = getValueController().getValueF();
		float vo = value_tranformer.transformValue( vi );
		setValueF( vo );
	}
	
	@Override
	public Object getAdapter( Class<?> clazz, Object arg ) {
		if( clazz == IControlEditor.class ) {
			return new ValueTransformerControlEditor( this );
		}
		if( clazz == IControlIO.class ) {
			return new ValueTransformerIO();
		}
		return super.getAdapter( clazz, arg );
	}

	@Override
	public void curveRemoved(CurveValueTransformer curve) 
	{
		if( curve == value_tranformer ) {
			//reset to identity
			setValueTransformer( null );
		}
		
	}

}
